<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <script src="jquery.min.js"></script>
  <style>
    html, body {
      margin: 0;
      height: 100%;
      overflow-x: hidden;
    }

    .loading-element {
      display: none;
      position: absolute;
      left: 50%;
      top: 50%;
      height: 4px;
      width: 128px;
      transform: translate(-50%, -50%);
      user-select: none;
      pointer-events: none;
      animation: loading-element-enter .2s ease .5s;
      animation-fill-mode: backwards;
      background-color: #eee;
    }

    .loading-progress {
      position: absolute;
      left: 0;
      top: 0;
      bottom: 0;
      width: 100%;
      transform-origin: 0% 50%;
      background-color: #aaa;
      transition: transform .2s ease-in-out;
    }

    @keyframes loading-element-enter {
      from { opacity: 0; }
      to { opacity: 1; }
    }

    body.is-loading .loading-element {
      display: block;
    }

    body.is-loading .prototype-container {
      display: none;
    }

    .prototype-container {
      position: absolute;
      height: 100%;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
    }

    .prototype-container ::-webkit-scrollbar {
      display: none;
    }

    .artboard {
      position: absolute;
      left: 0;
      top: 0;
      right: 0;
      bottom: 0;
      opacity: 0;
      display: none;
      box-shadow: 0 0 0 1px rgba(0, 0, 0, .12);
      overflow: hidden;
    }

    .artboard.is-active {
      opacity: 1;
      display: block;
    }

    .artboard-scroll-container,
    .artboard-fixed-container {
      position: absolute;
      left: 0;
      top: 0;
      right: 0;
      bottom: 0;
    }

    .artboard-fixed-container {
      pointer-events: none;
    }

    .artboard-scroll-container {
      overflow: scroll;
    }

    .artboard-content {
      position: absolute;
      left: 0;
      top: 0;
      background-size: contain;
    }

    .hotspot {
      cursor: pointer;
      position: absolute;
      opacity: 0;
    }

    body[can-show-hotspots] .hotspot {
      background-color: rgba(239, 108, 0, .2);
      box-shadow:
          0 0 0 3px rgba(239, 108, 0, .5) inset,
          0 4px 8px rgba(239, 108, 0, .25);
    }

    .highlight-hotspots .hotspot {
      animation: hotspotAnimation .6s ease;
    }

    @keyframes hotspotAnimation {
      0% {
        opacity: 0;
      }
      50% {
        opacity: 1;
      }
      100% {
        opacity: 0;
      }
    }
  </style>
</head>
<body class="is-loading"
    can-show-hotspots>

  <div class="loading-element">
      <div class="loading-progress"></div>
  </div>
  <div class="prototype-container"></div>

  <script>

    class Proto {
      constructor(prototypeData) {
        this.prototypeData = prototypeData;
        this.buildUi();
      }

      preloadImages() {
        let $loadingProgress = $('.loading-progress');
        let numLoaded = 0;
        let numTotal = 0;

        function updateProgress_() {
          let scale = numTotal ? numLoaded / numTotal : 0;
          $loadingProgress.css('transform', `scaleX(${scale})`);
        }

        updateProgress_();

        function preloadImageUrl_(url) {
          return new Promise((resolve, reject) => {
            let img = document.createElement('img');
            img.src = url;
            img.onload = () => {
              ++numLoaded;
              updateProgress_();
              resolve();
            };
            img.onerror = () => {
              ++numLoaded;
              updateProgress_();
              console.error(`Error loading ${url}`); resolve();
            };
          });
        }

        let visitedArtboards = [];
        let imageUrls = new Set([]);

        let promises = [];
        Object.keys(this.prototypeData.artboards).forEach(id => {
          promises.push(preloadImageUrl_(`${id}.png`));
          if (this.prototypeData.artboards[id].hasFixedLayers) {
            promises.push(preloadImageUrl_(`${id}_fixed.png`));
          }
        });

        numTotal = promises.length;
        return Promise.all(promises);
      }

      buildUi() {
        this.buildArtboards();

        this.preloadImages().then(() => $('body').removeClass('is-loading'));

        if (this.prototypeData.title) {
          document.title = this.prototypeData.title;
        }

        $(window).on('hashchange', () => {
          this.setArtboardVisible(this.getUrlInfo().artboardId);
        });

        $(document).click(() => {
          if (this.shouldSuppressHotspotReveal_) {
            return;
          }

          $(document.body).removeClass('highlight-hotspots');
          let f = document.body.offsetWidth;
          $(document.body).addClass('highlight-hotspots');
        });

        $(window).on('resize', () => this.resize());

        this.setArtboardVisible(this.getUrlInfo().artboardId);
      }

      resize() {
        let width = this.startArtboard.viewportWidth || this.startArtboard.width;
        let height = this.startArtboard.viewportHeight || this.startArtboard.height;
        if (this.currentArtboard.viewportWidth && this.currentArtboard.viewportHeight) {
          width = this.currentArtboard.viewportWidth;
          height = this.currentArtboard.viewportHeight;
        }

        let xScale = window.innerHeight / height;
        let yScale = window.innerWidth / width;
        $('.prototype-container')
            .css({
              width: width,
              height: height,
              zoom: Math.min(1, Math.min(xScale, yScale)),
            });
      }

      getUrlInfo() {
        let hash = window.location.hash;

        return {
          artboardId: hash ? hash.substring(1) : this.prototypeData.flowStartArtboardId,
        };
      }

      buildArtboards() {
        Object.keys(this.prototypeData.artboards).forEach(id => {
          let artboardData = this.prototypeData.artboards[id];
          let $artboard = $('<div>')
              .addClass('artboard')
              .attr('data-artboard-id', id)
              .appendTo('.prototype-container');

          // add scrollable content
          let $artboardScrollContainer = $('<div>')
              .addClass('artboard-scroll-container')
              .appendTo($artboard);
          let $artboardScrollableContent = $('<div>')
              .addClass('artboard-content')
              .css({
                backgroundImage: `url(${id}.png)`,
                width: artboardData.width,
                height: artboardData.height,
              })
              .appendTo($artboardScrollContainer);

          // add fixed content
          if (artboardData.hasFixedLayers) {
            let $artboardFixedContainer = $('<div>')
                .addClass('artboard-fixed-container')
                .appendTo($artboard);
            let $artboardFixedContent = $('<div>')
                .addClass('artboard-content')
                .css({
                  backgroundImage: `url(${id}_fixed.png)`,
                  width: artboardData.width,
                  height: artboardData.height,
                })
                .appendTo($artboardFixedContainer);
          }

          if (id == this.prototypeData.flowStartArtboardId) {
            // this is the start artboard
            this.startArtboard = artboardData;
            this.currentArtboard = artboardData;
          }

          artboardData.hotspots.forEach(hotspotData => {
            let $hotspot = $('<div>')
              .addClass('hotspot')
              .attr('data-artboard-id', id)
              .css({
                left: hotspotData.rectangle.x,
                top: hotspotData.rectangle.y,
                width: hotspotData.rectangle.width,
                height: hotspotData.rectangle.height,
              })
              .appendTo(hotspotData.isFixed
                  ? $artboard // don't add to $artboardFixedContent because of pointer-events:none
                  : $artboardScrollableContent);
            $hotspot.click(event => {
              this.gotoTarget(hotspotData.target)
              event.stopPropagation();
            });
          });
        });
      }

      gotoTarget(target) {
        if (target == 'back') {
          history.back();
          return;
        }

        this.gotoArtboard(target);
      }

      gotoArtboard(artboardId) {
        window.location.href= '#' + artboardId;
      }

      setArtboardVisible(artboardId) {
        this.currentArtboard = this.prototypeData.artboards[artboardId];

        $('.artboard-scroll-container').scrollLeft(0).scrollTop(0);

        $(document.body).removeClass('highlight-hotspots');
        $('.artboard').removeClass('is-active');
        $(`.artboard[data-artboard-id="${artboardId}"]`).addClass('is-active');

        this.resize();
      }
    }

  </script>
  <script>
    new Proto(
      {"title":"鸣鸟web端","flowStartArtboardId":"5C4D8146-4B8D-40CD-9CDB-44050145EA96","artboards":{"5C4D8146-4B8D-40CD-9CDB-44050145EA96":{"title":"iPhone 8备份","width":750,"height":8090,"viewportWidth":375,"viewportHeight":667,"hotspots":[],"hasFixedLayers":false}}}
    );
  </script>

</body>
</html>
